package logger

import (
	"fmt"
	"os"
	"path/filepath"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

var (
	// 日志根目录（绝对路径）
	LogRootDir string
	logger     *zap.Logger
	config     Config

	// 分类日志记录器
	systemLogger    *zap.Logger
	operationLogger *zap.Logger
	networkLogger   *zap.Logger
	otherLogger     *zap.Logger
)

// 日志类别常量
const (
	CategorySystem      = "system"      // 系统日志：系统启动、关闭、配置加载等基础事件
	CategoryOperation   = "operation"   // 操作日志：用户或系统的操作行为
	CategoryDevice      = "device"      // 设备日志：与硬件设备相关的事件（归入其他日志）
	CategorySecurity    = "security"    // 安全日志：与安全相关的事件（归入操作日志）
	CategoryPerformance = "performance" // 性能日志：系统性能指标（归入其他日志）
	CategoryNetwork     = "network"     // 网络日志：网络通信相关事件
	CategoryOther       = "other"       // 其他日志：未归类的日志
)

// 日志类别映射到文件
var categoryToFile = map[string]string{
	CategorySystem:      "system.log",
	CategoryOperation:   "operation.log",
	CategorySecurity:    "operation.log", // 安全日志归入操作日志
	CategoryNetwork:     "network.log",
	CategoryDevice:      "other.log", // 设备日志归入其他日志
	CategoryPerformance: "other.log", // 性能日志归入其他日志
	CategoryOther:       "other.log",
}

// 获取日志类别对应的日志记录器
func getCategoryLogger(category string) *zap.Logger {
	switch category {
	case CategorySystem:
		return systemLogger
	case CategoryOperation, CategorySecurity:
		return operationLogger
	case CategoryNetwork:
		return networkLogger
	case CategoryDevice, CategoryPerformance, CategoryOther:
		return otherLogger
	default:
		return otherLogger
	}
}

type Config struct {
	EnableConsole       bool   // 是否输出到控制台
	EnableCaller        bool   // 是否输出调用者信息
	LogDirByServiceName string // 服务日志目录名（例如：config_server, monitor_server等）
	MaxSize             int    // 单个日志文件最大尺寸，单位 MB
	MaxBackups          int    // 保留的旧日志文件最大数量
	MaxAge              int    // 保留的旧日志文件最大天数

	// 日志级别配置
	SystemLogLevel    zapcore.Level // system.log 的最低日志级别
	OperationLogLevel zapcore.Level // operation.log 的最低日志级别
	NetworkLogLevel   zapcore.Level // network.log 的最低日志级别
	OtherLogLevel     zapcore.Level // other.log 的最低日志级别

	// 兼容旧版的配置（仅用于向后兼容，实际不再使用）
	AppLogLevel    zapcore.Level // app.log 的最低日志级别（兼容旧版）
	ErrorLogLevel  zapcore.Level // error.log 的最低日志级别（兼容旧版）
	DebugLogLevel  zapcore.Level // debug.log 的最低日志级别（兼容旧版）
	EnableDebugLog bool          // 是否启用debug.log（兼容旧版）
}

// 默认配置
var defaultConfig = Config{
	EnableConsole:       true,
	EnableCaller:        true,
	LogDirByServiceName: "default",
	MaxSize:             5,
	MaxBackups:          5,
	MaxAge:              30,

	// 日志级别默认配置
	SystemLogLevel:    zapcore.InfoLevel,
	OperationLogLevel: zapcore.InfoLevel,
	NetworkLogLevel:   zapcore.InfoLevel,
	OtherLogLevel:     zapcore.InfoLevel,

	// 兼容旧版的配置（仅用于向后兼容，实际不再使用）
	AppLogLevel:    zapcore.InfoLevel,
	ErrorLogLevel:  zapcore.ErrorLevel,
	DebugLogLevel:  zapcore.DebugLevel,
	EnableDebugLog: false,
}

// init 函数完成日志包的初始化工作
func init() {
	// 1. 获取可执行文件所在目录的上级目录（cmd目录）
	exePath, err := os.Executable()
	if err != nil {
		fmt.Printf("获取可执行文件路径失败: %v\n", err)
		os.Exit(1)
	}
	fmt.Printf("exePath: %v\n", exePath)

	// 获取cmd目录（可执行文件所在目录的上级：bin -> xxx_server -> cmd）
	cmdDir := filepath.Dir(filepath.Dir(filepath.Dir(exePath)))

	// 设置日志根目录为cmd目录下的 logs
	LogRootDir = filepath.Join(cmdDir, "logs")
	fmt.Printf("LogRootDir: %v\n", LogRootDir)

	// 创建日志根目录
	if err := os.MkdirAll(LogRootDir, 0755); err != nil {
		fmt.Printf("创建日志根目录失败: %v\n", err)
		os.Exit(1)
	}

	// 设置默认配置
	config = defaultConfig

	// 创建日志记录器
	initLogger()
}

// 配置日志
func Configure(cfg Config) error {
	// 更新配置
	config = cfg

	// 检查服务日志目录是否存在，不存在则创建
	logDir := filepath.Join(LogRootDir, config.LogDirByServiceName)
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return fmt.Errorf("创建服务日志目录失败: %v", err)
	}

	// 初始化日志系统
	initLogger()
	return nil
}

func initLogger() {
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:       "T",
		LevelKey:      "L",
		NameKey:       "N",
		CallerKey:     "C",
		MessageKey:    "M",
		StacktraceKey: "S",
		LineEnding:    zapcore.DefaultLineEnding,
		EncodeLevel:   zapcore.CapitalLevelEncoder,
		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendString(t.Format("20060102150405"))
		},
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}

	// 配置日志目录
	logDir := filepath.Join(LogRootDir, config.LogDirByServiceName)

	// 系统日志
	systemLogRotate := &lumberjack.Logger{
		Filename:   filepath.Join(logDir, "system.log"),
		MaxSize:    config.MaxSize,
		MaxBackups: config.MaxBackups,
		MaxAge:     config.MaxAge,
		Compress:   true,
		LocalTime:  true,
	}

	// 操作日志
	operationLogRotate := &lumberjack.Logger{
		Filename:   filepath.Join(logDir, "operation.log"),
		MaxSize:    config.MaxSize,
		MaxBackups: config.MaxBackups,
		MaxAge:     config.MaxAge,
		Compress:   true,
		LocalTime:  true,
	}

	// 网络日志
	networkLogRotate := &lumberjack.Logger{
		Filename:   filepath.Join(logDir, "network.log"),
		MaxSize:    config.MaxSize,
		MaxBackups: config.MaxBackups,
		MaxAge:     config.MaxAge,
		Compress:   true,
		LocalTime:  true,
	}

	// 其他日志
	otherLogRotate := &lumberjack.Logger{
		Filename:   filepath.Join(logDir, "other.log"),
		MaxSize:    config.MaxSize,
		MaxBackups: config.MaxBackups,
		MaxAge:     config.MaxAge,
		Compress:   true,
		LocalTime:  true,
	}

	// 错误日志（所有类别的错误都会记录到这里）
	errorLogRotate := &lumberjack.Logger{
		Filename:   filepath.Join(logDir, "error.log"),
		MaxSize:    config.MaxSize,
		MaxBackups: config.MaxBackups,
		MaxAge:     config.MaxAge,
		Compress:   true,
		LocalTime:  true,
	}

	// 创建分类日志核心
	systemCore := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.AddSync(systemLogRotate),
		config.SystemLogLevel,
	)

	operationCore := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.AddSync(operationLogRotate),
		config.OperationLogLevel,
	)

	networkCore := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.AddSync(networkLogRotate),
		config.NetworkLogLevel,
	)

	otherCore := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.AddSync(otherLogRotate),
		config.OtherLogLevel,
	)

	// 错误日志核心（记录所有Error及以上级别的日志）
	errorCore := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.AddSync(errorLogRotate),
		zapcore.ErrorLevel,
	)

	// 创建分类日志记录器
	var opts []zap.Option
	if config.EnableCaller {
		opts = append(opts, zap.AddCaller(), zap.AddCallerSkip(2))
	}

	// 创建控制台输出核心（如果启用）
	var consoleCore zapcore.Core
	if config.EnableConsole {
		consoleCore = zapcore.NewCore(
			zapcore.NewJSONEncoder(encoderConfig),
			zapcore.AddSync(os.Stdout),
			zapcore.InfoLevel,
		)

		// 将控制台输出添加到各个日志记录器的核心中
		systemCore = zapcore.NewTee(systemCore, consoleCore)
		operationCore = zapcore.NewTee(operationCore, consoleCore)
		networkCore = zapcore.NewTee(networkCore, consoleCore)
		otherCore = zapcore.NewTee(otherCore, consoleCore)
	}

	// 创建分类日志记录器（包含错误日志核心）
	systemLogger = zap.New(zapcore.NewTee(systemCore, errorCore), opts...)
	operationLogger = zap.New(zapcore.NewTee(operationCore, errorCore), opts...)
	networkLogger = zap.New(zapcore.NewTee(networkCore, errorCore), opts...)
	otherLogger = zap.New(zapcore.NewTee(otherCore, errorCore), opts...)

	// 创建主日志记录器（用于兼容旧接口）
	allCores := []zapcore.Core{systemCore, operationCore, networkCore, otherCore, errorCore}
	if config.EnableConsole {
		allCores = append(allCores, consoleCore)
	}
	logger = zap.New(zapcore.NewTee(allCores...), opts...)
}

// 原有的日志函数保持不变，保证兼容性
func Debug(msg string, fields ...zapcore.Field) {
	// 将Debug日志路由到其他日志
	otherLogger.Debug(msg, fields...)
}

func Info(msg string, fields ...zapcore.Field) {
	// 将Info日志路由到其他日志
	otherLogger.Info(msg, fields...)
}

func Warn(msg string, fields ...zapcore.Field) {
	// 将Warn日志路由到其他日志
	otherLogger.Warn(msg, fields...)
}

func Error(msg string, fields ...zapcore.Field) {
	// 将Error日志路由到其他日志
	otherLogger.Error(msg, fields...)
}

func Fatal(msg string, fields ...zapcore.Field) {
	// 将Fatal日志路由到其他日志
	otherLogger.Fatal(msg, fields...)
}

// 在程序结束时同步日志
func Sync() {
	systemLogger.Sync()
	operationLogger.Sync()
	networkLogger.Sync()
	otherLogger.Sync()
	logger.Sync()
}

// 新增的带分类的日志函数

// LogWithCategory 记录带分类的日志
func logWithCategory(level zapcore.Level, category string, msg string, fields ...zapcore.Field) {
	// 添加分类字段
	newFields := append([]zapcore.Field{zap.String("category", category)}, fields...)

	// 获取对应的日志记录器
	categoryLogger := getCategoryLogger(category)

	// 根据级别调用对应的日志函数
	switch level {
	case zapcore.DebugLevel:
		categoryLogger.Debug(msg, newFields...)
	case zapcore.InfoLevel:
		categoryLogger.Info(msg, newFields...)
	case zapcore.WarnLevel:
		categoryLogger.Warn(msg, newFields...)
	case zapcore.ErrorLevel:
		categoryLogger.Error(msg, newFields...)
	case zapcore.FatalLevel:
		categoryLogger.Fatal(msg, newFields...)
	default:
		categoryLogger.Info(msg, newFields...)
	}
}

// 系统日志函数
func SystemDebug(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.DebugLevel, CategorySystem, msg, fields...)
}

func SystemInfo(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.InfoLevel, CategorySystem, msg, fields...)
}

func SystemWarn(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.WarnLevel, CategorySystem, msg, fields...)
}

func SystemError(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.ErrorLevel, CategorySystem, msg, fields...)
}

func SystemFatal(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.FatalLevel, CategorySystem, msg, fields...)
}

// 操作日志函数
func OperationDebug(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.DebugLevel, CategoryOperation, msg, fields...)
}

func OperationInfo(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.InfoLevel, CategoryOperation, msg, fields...)
}

func OperationWarn(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.WarnLevel, CategoryOperation, msg, fields...)
}

func OperationError(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.ErrorLevel, CategoryOperation, msg, fields...)
}

func OperationFatal(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.FatalLevel, CategoryOperation, msg, fields...)
}

// 安全日志函数（归入操作日志）
func SecurityDebug(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.DebugLevel, CategorySecurity, msg, fields...)
}

func SecurityInfo(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.InfoLevel, CategorySecurity, msg, fields...)
}

func SecurityWarn(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.WarnLevel, CategorySecurity, msg, fields...)
}

func SecurityError(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.ErrorLevel, CategorySecurity, msg, fields...)
}

func SecurityFatal(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.FatalLevel, CategorySecurity, msg, fields...)
}

// 网络日志函数
func NetworkDebug(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.DebugLevel, CategoryNetwork, msg, fields...)
}

func NetworkInfo(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.InfoLevel, CategoryNetwork, msg, fields...)
}

func NetworkWarn(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.WarnLevel, CategoryNetwork, msg, fields...)
}

func NetworkError(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.ErrorLevel, CategoryNetwork, msg, fields...)
}

func NetworkFatal(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.FatalLevel, CategoryNetwork, msg, fields...)
}

// 设备日志函数（归入其他日志）
func DeviceDebug(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.DebugLevel, CategoryDevice, msg, fields...)
}

func DeviceInfo(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.InfoLevel, CategoryDevice, msg, fields...)
}

func DeviceWarn(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.WarnLevel, CategoryDevice, msg, fields...)
}

func DeviceError(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.ErrorLevel, CategoryDevice, msg, fields...)
}

func DeviceFatal(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.FatalLevel, CategoryDevice, msg, fields...)
}

// 性能日志函数（归入其他日志）
func PerformanceDebug(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.DebugLevel, CategoryPerformance, msg, fields...)
}

func PerformanceInfo(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.InfoLevel, CategoryPerformance, msg, fields...)
}

func PerformanceWarn(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.WarnLevel, CategoryPerformance, msg, fields...)
}

func PerformanceError(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.ErrorLevel, CategoryPerformance, msg, fields...)
}

func PerformanceFatal(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.FatalLevel, CategoryPerformance, msg, fields...)
}

// 其他日志函数
func OtherDebug(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.DebugLevel, CategoryOther, msg, fields...)
}

func OtherInfo(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.InfoLevel, CategoryOther, msg, fields...)
}

func OtherWarn(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.WarnLevel, CategoryOther, msg, fields...)
}

func OtherError(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.ErrorLevel, CategoryOther, msg, fields...)
}

func OtherFatal(msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.FatalLevel, CategoryOther, msg, fields...)
}

// 通用分类日志函数
func LogDebug(category string, msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.DebugLevel, category, msg, fields...)
}

func LogInfo(category string, msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.InfoLevel, category, msg, fields...)
}

func LogWarn(category string, msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.WarnLevel, category, msg, fields...)
}

func LogError(category string, msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.ErrorLevel, category, msg, fields...)
}

func LogFatal(category string, msg string, fields ...zapcore.Field) {
	logWithCategory(zapcore.FatalLevel, category, msg, fields...)
}
